package de.koller.worlders.engine.tiles.data;

import de.koller.oceanFramework.tree.Child;
import de.koller.oceanFramework.util.ColorIntUtil;
import de.koller.worlders.WSea;
import de.koller.worlders.engine.tiles.Tile;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TileHolder extends WSea {
		
	public static final int INVALIDATE_TIME = 5000;
	
	@Child final TileLoader tileLoader = new TileLoader();
	
	private boolean locked = false;
	private int accessPerFrame = 0;
	private int removedTiles = 0;
	private final Map<String, TileWrap> tileBucket = new HashMap<>();
	
	public TileHolder() {
		this.setIgnoreChildRender( true );
		this.setIgnoreChildUpdate( true );
	}
	
	public void addTileNode( Tile t ) {
		t.generate( wroot );
	}
	
	synchronized public void timeoutTile() {
		if( locked )
			return;
		
		List<String> keysToRemove = new ArrayList<>();
		long time = wroot.getTime() - INVALIDATE_TIME;
		
		for( TileWrap t : tileBucket.values() )
			if( t.getLastUse() < time ) {
				t.releaseWrap();
				keysToRemove.add( t.assignedKey );
			}
		
		removedTiles = keysToRemove.size();
		for( String k : keysToRemove )
			tileBucket.remove( k );
	}
	
	synchronized public void clearAllTiles() {
		if( locked )
			return;
		
		locked = true;
		for( TileWrap t : tileBucket.values() )
			t.releaseWrap();
		tileBucket.clear();
		locked = false;
		
		tileLoader.mapDataDist.reloadData();
	}
	
	public void reloadTile( int tx, int ty ) {
		removeTile( tx, ty );
		getTile( tx, ty );
		wroot.tileChanged( tx, ty );
	}

	public void reloadData( boolean story ) {
		tileLoader.reloadData( story );
	}
	
	synchronized public TileWrap getTile( int tx, int ty ) {
		if( locked )
			return null;
		
		accessPerFrame++;
		
		String key = TileKey.toKey( tx, ty );
		TileWrap t = tileBucket.get( key );
		if( t != null ) {
			t.setLastUse();
			return t;
		}
		
		t = new TileWrap( tileLoader, tx, ty );
		t.assignedKey = key;
		tileBucket.put( key, t );
		t.setLastUse();
		return t;
	}
	
	public void removeTile( int tx, int ty ) {
		String key = TileKey.toKey( tx, ty );
		getTile( tx, ty ).releaseWrap();
		tileBucket.remove( key );
	}
	
	public void save() {
		tileLoader.saveMaps();
	}

	public int getMapData( int tx, int ty ) {
		return tileLoader.getMapData( tx, ty ).getMapData( tx, ty );
	}
	
	public int getLightData( int tx, int ty ) {
		return tileLoader.getMapData( tx, ty ).getLightData( tx, ty );
	}
	
	public int getDrawData( int tx, int ty ) {
		return tileLoader.getMapData( tx, ty ).getDrawData( tx, ty );
	}
	
	public void setMapData( int tx, int ty, int data ) {
		tileLoader.getMapData( tx, ty ).setMapData( tx, ty, data );
	}
	
	public void setLightData( int tx, int ty, int data ) {
		tileLoader.getMapData( tx, ty ).setLightData( tx, ty, data );
	}

	public void setDrawData( int tx, int ty, int data ) {
		tileLoader.getMapData( tx, ty ).setDrawData( tx, ty, data );
	}

	
	public void changeMapData( int tx, int ty, int base, int disp, int deco, int fog ) {
		this.setMapData( tx, ty, ColorIntUtil.change( this.getMapData( tx, ty ), base, disp, deco, fog ) );
	}
	
	public void changeLightData( int tx, int ty, int a, int r, int g, int b ) {
		this.setLightData( tx, ty, ColorIntUtil.change( this.getLightData( tx, ty ), a, r, g, b ) );
	}
	 
	public MapDetails getDetail( int tx, int ty ) {
		return tileLoader.getMapData( tx, ty ).getDetails();
	}

	public TileCreatorGen getCreatorMap() {
		return tileLoader.getCreatorMap();
	}

	public int getTileNumber() {
		return tileBucket.size();
	}

	public int getAccessPerFrame() {
		return accessPerFrame;
	}
	
	public void resetAccesPerFrame() {
		accessPerFrame = 0;
	}

	public int getRemovedTiles() {
		return removedTiles;
	}

	public int getLoadedMaps() {
		return tileLoader.mapDataDist.getLoadedMaps();
	}
	
	public Integer[] getMapDataTiles() {
		return tileLoader.mapDataDist.loadedTiles();
	}

	public boolean isLocked() {
		return locked;
	}
	
}
